home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpat2-1.000 / xpat2-1 / xpat2-1.04 / src / X-sound_FM.c < prev    next >
C/C++ Source or Header  |  1994-04-23  |  4KB  |  190 lines

  1. /*****************************************************************************/
  2. /*                                         */
  3. /*                                         */
  4. /*    X patience version 2 -- module X-sound-FM.c                 */
  5. /*                                         */
  6. /*    written by Michael Bischoff                         */
  7. /*    based on fmtest.c by Rob Hooft                         */
  8. /*    see COPYRIGHT.xpat2 for Copyright details                 */
  9. /*                                         */
  10. /*                                         */
  11. /*****************************************************************************/
  12. #include "X-pat.h"
  13.  
  14. /* FMTEST by Rob Hooft (hooft@chem.ruu.nl) */
  15. /* modified by M. Bischoff */
  16.  
  17. #include <ctype.h>
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <sys/stat.h>
  21. #include <errno.h>
  22. #include <getopt.h>
  23. #include <sys/soundcard.h>
  24.  
  25. static int sb;
  26. static char sbbuf[404];
  27. static int sbptr = 0;
  28.  
  29. static void sbflush(void) {
  30.     if (!sbptr) return;
  31.     
  32.     if (write(sb, sbbuf, sbptr) == -1) {
  33.     perror("write sb");
  34.     exit(EXIT_FAILURE);
  35.     }
  36.     
  37.     sbptr=0;
  38. }
  39.  
  40. static void sbwrite(char *msg) {
  41.     if (sbptr>400) sbflush();
  42.     
  43.     memcpy(&sbbuf[sbptr], msg, 4);
  44.     sbptr +=4;
  45. }
  46.  
  47. static void midich(char c) {
  48.     char buf[4];
  49.     
  50.     buf[0] = 5;
  51.     buf[1] = c;
  52.     sbwrite(buf);
  53. }
  54.  
  55. static void noteon(int chan,int pitch,int vol) {
  56.     char buf[4];
  57. #ifdef DEBUG
  58.     printf("Note on, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol);
  59. #endif
  60.     
  61.     if (chan >= 0) {
  62.     buf[0] = SEQ_FMNOTEON;
  63.     buf[1] = chan;
  64.     buf[2] = pitch;
  65.     buf[3] = vol;
  66.     sbwrite(buf);    
  67.     } else {
  68.     midich(0x90+chan);
  69.     midich(pitch);
  70.     midich(vol);
  71.     }
  72. }
  73.  
  74. static void noteoff(int chan,int pitch,int vol) {
  75.     char buf[4];
  76. #ifdef DEBUG
  77.     printf("Note off, chan=%d pitch=%d vol=%d\n",chan+1,pitch,vol);    
  78. #endif
  79.     
  80.     if (chan >= 0) {
  81.     buf[0] = SEQ_FMNOTEOFF;
  82.     buf[1] = chan;
  83.     buf[2] = pitch;
  84.     buf[3] = vol;
  85.     sbwrite(buf);    
  86.     } else {
  87.     midich(0x80+chan);
  88.     midich(pitch);
  89.     midich(vol);
  90.     }
  91. }
  92.  
  93. static void wait(int delay) {
  94.     int jiffies;
  95.     jiffies = (delay << 8) | SEQ_WAIT;
  96.     sbwrite((char*)&jiffies);
  97. }
  98.  
  99. #define CHANNELS    4
  100.  
  101. static void do_music(XEvent *xev) {
  102.     static long mask = KeyPressMask | ButtonPressMask | ExposureMask;
  103.     /* | StructureNotifyMask  */
  104.     char buf[100];
  105.     int channel;
  106.     struct dong {
  107.     int off;
  108.     int volume;
  109.     int note;
  110.     } dong[CHANNELS];
  111.  
  112.     fprintf(stderr, "do_music called, audio = %d\n", audio);
  113.     XSync(dpy, 0);        /* wait for graphic to be finished */
  114.     if (!audio) {
  115.     wait_event(xev);
  116.     return;
  117.     }
  118.  
  119. start:
  120.     while (XCheckWindowEvent(dpy, table, mask, xev)) {
  121.     /* printf("xev->type is %d\n", xev->type); */
  122.     if (xev->xany.type == Expose)
  123.         redraw_table((XExposeEvent *)xev);
  124.     else if (xev->xany.type != NoExpose)
  125.         return;
  126.     }
  127.     if ((sb=open("/dev/sequencer", O_WRONLY, 0))==-1) {
  128.     sleep(1);
  129.     goto start;    /* retry the open */
  130.     }
  131.  
  132.     for (channel = 0; channel < CHANNELS; ++channel) {
  133.     buf[0] = SEQ_FMPGMCHANGE;
  134.     buf[1] = channel;
  135.     buf[2] = 9; /* nr_instr; */
  136.     sbwrite(buf);
  137.     dong[channel].off = 0;
  138.     }
  139.     channel = 0;
  140.     {   int tm, tt;
  141.     struct dong *ch;
  142.     tt = tm = 3;
  143.  
  144.     for (;;) {
  145.         int delay;
  146.         /* select next channel */
  147.         channel = (channel + 1) % CHANNELS;
  148.         ch = dong + channel;
  149.           wait(tm);
  150.         if (dong[channel].off) {
  151.         noteoff(channel, ch->note, ch->volume);
  152.         tt += 3;
  153.         wait (tm+=3);
  154.         }
  155.         ch->off = 1;
  156.         ch->note = 5 + rand() % 30;
  157.         ch->volume = 32 + rand() % 32;
  158.          noteon(channel, ch->note, ch->volume);
  159.         delay = 5 + rand() % 40;
  160.         tt += delay;
  161.         tm += delay;
  162.          while (tt > 200) {
  163.              sbflush();
  164.             while (XCheckWindowEvent(dpy, table, mask, xev)) {
  165.             /* printf("xev->type is %d\n", xev->type); */
  166.             if (xev->xany.type == Expose)
  167.             redraw_table((XExposeEvent *)xev);
  168.             else if (xev->type != NoExpose) {    /* abort */
  169.             for (channel = 0; channel < CHANNELS; ++channel)
  170.                 if (dong[channel].off)
  171.                 noteoff(channel, dong[channel].note, dong[channel].volume);
  172.             sbflush();
  173.             close(sb);
  174.             return;
  175.             }
  176.         }
  177.         tt -= 100;    /* 100 jiffies = 1 second */
  178.         sleep(1);
  179.         }
  180.         }
  181.     }
  182. }
  183.  
  184. void play_sound(const char *filename) {
  185.     if (!strcmp(filename, "success") && checksound()) {
  186.     XEvent xev;
  187.     do_music(&xev);
  188.     }
  189. }
  190.